package org.spring.boot.fusion.common.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import lombok.extern.slf4j.Slf4j;

import org.aspectj.lang.Signature;
import org.aspectj.lang.reflect.MethodSignature;
import org.spring.boot.fusion.common.exception.ServiceErrorStatus;
import org.spring.boot.fusion.common.exception.ServiceRunTimeException;
import org.spring.boot.fusion.common.exception.ServiceWirteLogs;
import org.spring.boot.fusion.common.properties.FusionAopLogProperties;
import org.spring.boot.fusion.common.tools.HttpServletTool;
import org.spring.boot.fusion.common.tools.JsonTool;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@Aspect
@Component
public class ControllerAop {

	@Autowired(required = false)
	private FusionLogsService fusionLogsService;
	@Autowired
	private FusionAopLogProperties fusionAopLogProperties;

	@Pointcut(value = "within(@org.springframework.web.bind.annotation.RestController *)")
	private void restControllerMethod() {

	}

	@Around("restControllerMethod()")
	public Object doAroundService(ProceedingJoinPoint joinPoint) {
		Object proceed = null;
		if (!fusionAopLogProperties.isLogFlag()) {
			try {
				proceed = joinPoint.proceed();
			} catch (Throwable e) {
				ServiceWirteLogs.error(e);
				throw new ServiceRunTimeException(ServiceErrorStatus.REQUEST_ERROR, e.getMessage());
			}
			return proceed;
		}
		try {
			MethodsParameterBean methodsParameterBean = new MethodsParameterBean();
			HttpServletRequest request = HttpServletTool.getRequest();
			if (request != null) {
				methodsParameterBean.setMethodsType(request.getMethod());
				methodsParameterBean.setContentType(request.getContentType());
				methodsParameterBean.setServerName(request.getServerName());
				methodsParameterBean.setUri(request.getRequestURI());
				methodsParameterBean.setUrl(request.getRequestURL().toString());
				methodsParameterBean.setParams(joinPoint.getArgs());
			}
			Signature sig = joinPoint.getSignature();
			MethodSignature msig = (MethodSignature) sig;
			Object target = joinPoint.getTarget();
			Method method = target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
			PostMapping postMapping = method.getAnnotation(PostMapping.class);
			if (postMapping != null) {
				methodsParameterBean.setMethodsDescribe(postMapping.name());
			}
			GetMapping getMapping = method.getAnnotation(GetMapping.class);
			if (getMapping != null) {
				methodsParameterBean.setMethodsDescribe(getMapping.name());
			}
			RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
			if (requestMapping != null) {
				methodsParameterBean.setMethodsDescribe(requestMapping.name());
			}
			if (fusionLogsService != null) {
				fusionLogsService.requestLogs(methodsParameterBean);
			} else {
				log.info("请求入参:{}", JsonTool.ObjectToJson(methodsParameterBean));
			}
		} catch (Exception e) {
			log.info("日志收集异常:{}", e.getMessage());
		}
		try {
			proceed = joinPoint.proceed();
		} catch (Throwable e) {
			ServiceWirteLogs.error(e);
			throw new ServiceRunTimeException(ServiceErrorStatus.REQUEST_ERROR, e.getMessage());
		}
		if (fusionLogsService != null) {
			return fusionLogsService.responseLogs(proceed);
		} else {
			log.info("请求出参:{}", JsonTool.ObjectToJson(proceed));
			return proceed;
		}
	}
}
